package littlecyberwar.ui;

import javax.swing.*;
import java.awt.geom.*;
import java.awt.*;
import java.io.*;
import java.util.*;

import littlecyberwar.ui.*;
import littlecyberwar.util.*;
import ModuleBuilder.model.*;

/**
 * Title:        LittleCyberWar
 * Description:  A online PBEM or PBC (play be Chat) Miniature utility
 * Copyright:    Copyright (c) 2001
 * Company:      S&S Enterprise
 * @author Milton Soong
 * @version 1.0
 * 
 *  this class is the model for any onboard moveable ElementOld (units)
 * Right now it's assumed that one ElementOld = one Unit, 
 * In the future we;ll add multiple ElementOld into a unit
 */
//

public class Element implements Serializable {

  /**
   * The straight unrotated rectangle of the ElementOld
   */
  transient Rectangle2D.Double r;

  /**
   * The already rotated shape that's being used to paint on to the board
   */
  transient Shape finalShape;

  /**
   * represent the current on board location of the ElementOld.
   */
  AffineTransform trans;

  /**
   * The right/left front of the unit (used to speed up pivoting).
   */
  transient Point2D.Double leftFrontP, rightFrontP;  // used as base of pivot

  /**
   * The width & height of the unit icon in pixels when the unit is lined
   * straight up.
   */
  double width,height;

  /**
   * The large picture that get's displayed in the top right corner when the
   * Unit is selected.
   */
  ImageIcon icon, sideIcon;

  /**
   * The scenario wide universal ElementOld id
   */
  Integer id;

  /**
   * The ElementOld name that gets printed
   */
  String name;
  
  // the unit 
  UnitModel unit;
  
  boolean onboard;	// if true, it's onboard, else it's still in a tray
  
  // used by ea ElementOld to keep track in case it's selected
  // volatile Shape selectedRectangle;
  
  /**
   * All the newer properties are stored in the newProps as to avoid changing class signature
   */
  HashMap newProps;	

  public Element(int x, int y, int w, int h) {
    sideIcon = ControlPanel.sideViewImage;
    init(x,y,w,h, null, sideIcon);
  }

  public Element (int x, int y, ImageIcon image) {
    int w = image.getIconWidth();
    int h = image.getIconHeight();
    sideIcon = ControlPanel.sideViewImage;
    init(x,y,w,h, image, sideIcon);
  }

  public Element (int x, int y, ImageIcon image, ImageIcon sideImage) {
    int w = image.getIconWidth();
    int h = image.getIconHeight();
    if ( sideImage == null ){
		sideImage = ControlPanel.sideViewImage;
    }
    init(x,y,w,h, image, sideImage);
  }

  protected void init(int x, int y, int w, int h, ImageIcon image, ImageIcon side) {
    icon = image;
    sideIcon = side;
    Integer in = new Integer(w);
    Integer hin = new Integer(h);
    width = in.doubleValue();
    height= hin.doubleValue();
	setupBaseRectangle();
    trans = new AffineTransform();
    trans.translate(x,y);
	setupFinalShape();
//    leftFrontP = new Point2D.Double(0,0);
//    rightFrontP = new Point2D.Double(w,0);
	setupFrontCornerPoints();
    onboard=false;
	newProps = new HashMap(3);
  }
  
  /**
   * THis is called after a load from sav file is made in order to 
   * setup the transient field
   * 
   * Has to be called after trans and r are set
   */
  public void setupFinalShape() {
	finalShape = trans.createTransformedShape(r);
	
	// TOTAL HACK! due to not wanting to change the element signature
	// will setup the side image from UNit Model from here
	//
	Image iconImage;
	if ( unit != null ){
		ImageElement sideImgElement = unit.getSideImage();
		ImageIcon sideImg = null;
		if (sideImgElement != null) {
			sideImg = sideImgElement.getFullImageIcon();
			if ( sideImg != null ){
				iconImage = sideImg.getImage();
				sideImg.setImage(iconImage);
			}		
		} else {
			sideImg = ControlPanel.sideViewImage;
		}
		sideIcon = sideImg;
	}
  }

  /**
   * THis is called after a load from sav file is made in order to 
   * setup the transient field
   */
  public void setupFrontCornerPoints() {
	leftFrontP = new Point2D.Double(0,0);
	rightFrontP = new Point2D.Double(width,0);
	return;
  }
  
  /**
   * THis is called after a load from sav file is made in order to 
   * setup the transient field
   */
  public void setupBaseRectangle() {
	r = new Rectangle2D.Double(0,0,width,height);
	}
  
  public void setElementId ( Integer idIn ) {
    id = idIn;
  }

  public Integer getElementId () {
    return ( id );
  }

  public void setName ( String nameIn ) {
    name = nameIn;
  }

  public String getName () {
    return ( name );
  }

  public double getWidth() {
    return ( width );
  }

  public double getHeight() {
    return ( height );
  }
    // is this the "select" rectangle and not the actual ElementOld shape..
    // !! This rectangle should be a flyweight from somewhere else..
  public Rectangle2D getRectangle() {
    return ( r );
  }

  public Point2D getFinalLeftFrontPoint() {
    // always do the transform live when needed
    return ( trans.transform(leftFrontP, null) );
  }

  public Point2D getFinalRightFrontPoint() {
    // always do the transform live when needed
    return ( trans.transform(rightFrontP, null) );
  }

  public void addTransform( AffineTransform t ) {
    trans.concatenate(t);
    finalShape = trans.createTransformedShape(r);
  }

  public void setTransFormAndFinalShape( AffineTransform t, Shape s ) {
    trans = t;
    finalShape = s;
	// Debug.out("ElementOld setTransFormAndFinalShape: t=" + trans.toString());
  }

	// this is called by the ModelChangeFacade when an ElementOld has been changed
	public void setTransform( AffineTransform t ) {
		trans = t;
		// Debug.out("ElementOld setTransformCall: t=" + trans.toString());
		// finalShape = trans.createTransformedShape(r);
		setupFinalShape();
	}
	
  public AffineTransform getTransform() {
    return ( trans );
  }

  public Shape getFinalShape() {
    return ( finalShape );
  }

  public ImageIcon getImageIcon() {
    return ( icon );
  }

  public ImageIcon getSideImage() {
    return( sideIcon );
  }
  
/**
 * @return
 */
public UnitModel getUnit() {
	return unit;
}

/**
 * @param model
 */
public void setUnit(UnitModel model) {
	unit = model;
}

/**
 * @return
 */
public boolean isOnboard() {
	return onboard;
}

/**
 * @param b
 */
public void setOnboard(boolean b) {
	onboard = b;
}

public Object getNewProps( String key ){
	return ( newProps.get(key));
}

public void setNewProps( String key, Object val ){
	newProps.put(key, val);
}


/**
 * Get the runtime overlay (handled by the delegate)
 * @return the overlay to be drawn
 */
//public Object getOverlayRuntime() {
//	Object val = null;
//	return ( val );
//}



}